package net.jxtz.jxtzos.controller.auth;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.jxtz.jxtzos.authentication.JwtUtils;
import net.jxtz.jxtzos.entity.auth.Role;
import net.jxtz.jxtzos.entity.auth.User;
import net.jxtz.jxtzos.entity.auth.UserRole;
import net.jxtz.jxtzos.entity.auth.dto.AddUserRoleDto;
import net.jxtz.jxtzos.entity.auth.dto.UpdatePasswordDto;
import net.jxtz.jxtzos.entity.auth.dto.UpdateUserRoleDto;
import net.jxtz.jxtzos.entity.web.R;
import net.jxtz.jxtzos.service.auth.UserRoleService;
import net.jxtz.jxtzos.service.auth.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author a123
 */
@RestController
@CrossOrigin
@RequestMapping("/user")
@Slf4j
public class UserController {

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public R add(@RequestBody User user){
        boolean save = userService.save(user);
        return save? R.ok(): R.error();
    }

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/add_from_admin", method = RequestMethod.POST)
    public R add(@RequestBody AddUserRoleDto addUserRoleDto) {
        User user = new User();
        user.setUserName(addUserRoleDto.getUserName());
        user.setNikeName(addUserRoleDto.getNikeName());
        user.setPassword(bCryptPasswordEncoder.encode(addUserRoleDto.getPassword()));
        user.setHeadUrl(addUserRoleDto.getHeadUrl());
        boolean save = userService.save(user);
        List<Long> roleId = addUserRoleDto.getRoles();
        List<UserRole> list = new ArrayList<>();
        roleId.forEach(aLong -> {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(aLong);
            list.add(userRole);
        });

        boolean b = userRoleService.saveBatch(list);
        return save && b ? R.ok():R.error();
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    public R delete(@PathVariable Long id){
        boolean b = userService.removeById(id);
        return b? R.ok():R.error();
    }

    @RequestMapping(value = "/deleteUserRole", method = RequestMethod.DELETE)
    public R delete(@RequestParam("userId") Long userId, @RequestParam("roleId") Long roleId){
        boolean remove = userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId).eq("role_id", roleId));
        return remove ? R.ok():R.error();
    }


    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public R list(){
        List<User> list = userService.list();
        return R.ok().data("list", list);
    }

    @RequestMapping(value = "/page", method = RequestMethod.GET)
    public R page(@RequestParam("pageNum") Integer pageNum, @RequestParam("pageSize") Integer pageSize, @RequestParam(value = "userName", required = false) String userName){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        // 如果userName == undefined
        if (!"".equals(userName)){
            userQueryWrapper.likeRight("user_name", userName);
        }
        Page<User> page = userService.page(new Page<User>(pageNum, pageSize), userQueryWrapper);
        long total = page.getTotal();
        List<User> records = page.getRecords();
        return R.ok().data("list", records).data("total", total);
    }

    @RequestMapping(value = "/checkUsername", method = RequestMethod.GET)
    public R checkUsername(@RequestParam("userName") String userName){
        User userName1 = userService.getOne(new QueryWrapper<User>().eq("user_name", userName), false);
        return userName1 == null ? R.ok().message("用户名可用"):R.error().code(51002).message("用户名已存在，请重新输入");
    }

    @RequestMapping(value = "/userInfo", method = RequestMethod.GET)
    public R token(@RequestParam("token") String token){
        token = token.replace(JwtUtils.TOKEN_PREFIX, "");
        String subject = JwtUtils.subject(token);
        User userName = userService.getOne(new QueryWrapper<User>().eq("user_name", subject));
        return R.ok().data("user", userName);
    }

    @RequestMapping(value = "/userInfoById", method = RequestMethod.GET)
    public R userInfo(@RequestParam("id") Long id){
        User byId = userService.getById(id);
        return R.ok().data("userInfo", byId);
    }


    @RequestMapping(value = "/getRoleByUserId", method = RequestMethod.GET)
    public R getRoleByUserId(@RequestParam("userId") Long userId){
        List<Role> rolesByUserId = userService.getRolesByUserId(userId);
        return R.ok().data("list", rolesByUserId);
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public R update(@RequestBody User user){
        boolean b = userService.updateById(user);
        return b? R.ok().data("userInfo", user):R.error();
    }

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping(value = "/updateUserAndUserRole", method = RequestMethod.POST)
    public R updateUserAndUserRole(@RequestBody UpdateUserRoleDto userRoleDto){
        User user = new User();
        BeanUtils.copyProperties(userRoleDto, user);
        List<Long> roles = userRoleDto.getRoles();
        List<UserRole> list = new ArrayList<>();
        roles.forEach(l -> {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(l);
            list.add(userRole);
        });
        userService.updateById(user);
        userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", user.getId()));
        userRoleService.saveBatch(list);
        return R.ok();
    }

    @RequestMapping(value = "/update_password", method = RequestMethod.POST)
    public R updatePassword(@RequestBody UpdatePasswordDto user){
        User userName = userService.getById(user.getId());
        boolean matches = bCryptPasswordEncoder.matches(user.getOldPassword(), userName.getPassword());
        if (matches){
            userName.setPassword(bCryptPasswordEncoder.encode(user.getNewPassword()));
            userService.updateById(userName);
            return R.ok();
        }else {
            return R.error().message("原密码不匹配，请重新输入");
        }
    }


    private final UserService userService;

    private final UserRoleService userRoleService;

    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public UserController(UserService userService, BCryptPasswordEncoder bCryptPasswordEncoder, UserRoleService userRoleService){
        this.userService = userService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.userRoleService = userRoleService;
    }
}
